package org.theSeed.base.utils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

/**
 * 地理位置工具
 */
public class GeoUtil {
    private static BigDecimal EarthRadius = BigDecimal.valueOf(6378137);

    /**
     * 距离计算
     * @param latitude1
     * @param longitude1
     * @param latitude2
     * @param longitude2
     * @return
     */
    public static BigDecimal distanceByLatLong(BigDecimal latitude1, BigDecimal longitude1, BigDecimal latitude2, BigDecimal longitude2) {
        if (latitude1.compareTo(BigDecimal.ZERO) <= 0 || longitude1.compareTo(BigDecimal.ZERO) <= 0 || latitude2.compareTo(BigDecimal.ZERO) <= 0 || longitude2.compareTo(BigDecimal.ZERO) <= 0) {
            return BigDecimal.ZERO;
        }


        // 将角度转换为弧度
        BigDecimal radLat1 = latitude1.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128);
        BigDecimal radLat2 = latitude2.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128);

        BigDecimal x = latitude1.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128)
                .subtract(latitude2.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128));
        BigDecimal y = longitude1.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128)
                .subtract(longitude2.multiply(BigDecimal.valueOf(Math.PI)).divide(BigDecimal.valueOf(180), MathContext.DECIMAL128));

        BigDecimal distance = BigDecimal.valueOf(2).multiply(BigDecimal.valueOf(Math.asin(Math.sqrt(Math.pow(Math.sin(x.doubleValue() / 2), 2)
                        + Math.cos(radLat1.doubleValue()) * Math.cos(radLat2.doubleValue()) * Math.pow(Math.sin(y.doubleValue() / 2), 2)))))
                .multiply(EarthRadius);

        // 四舍五入到一位小数
        return distance.setScale(1, RoundingMode.HALF_UP);
    }

    /**
     * 计算给定距离的经纬度边界
     * @param lat 中心纬度
     * @param lng 中心经度
     * @param distance 距离(米)
     * @return double数组 {minLat, minLng, maxLat, maxLng}
     */
    public static BigDecimal[] calculateBoundingBox(BigDecimal lat, BigDecimal lng, BigDecimal distance) {
        BigDecimal radios = BigDecimal.valueOf(180 / Math.PI);
        // 计算纬度偏移
        BigDecimal latOffset = distance.divide(EarthRadius,MathContext.DECIMAL128).multiply(radios);
        BigDecimal minLat = lat.subtract(latOffset);
        BigDecimal maxLat = lat.add(latOffset);

        // 计算经度偏移（考虑纬度变化）
        double cos = Math.cos(Math.toRadians(lat.doubleValue()));
        BigDecimal lngOffset = distance.divide(EarthRadius.multiply(BigDecimal.valueOf(Math.cos(Math.toRadians(lat.doubleValue())))),MathContext.DECIMAL128).multiply(radios);
        BigDecimal minLng = lng.subtract(lngOffset);
        BigDecimal maxLng = lng.add(lngOffset);

        return new BigDecimal[]{minLat, minLng, maxLat, maxLng};
    }
}